// Copyright 2024 Administrator
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { MinioClientService } from "src/core/system/minio/minio.service";
import { DataSource, Repository } from "typeorm";
import { FavoriteForm } from "../dto/create-track.dto";
import { TrackPageQuery } from "../dto/search-tracklist.dto";
import { Track } from "../entities/track.entity";
import { ITrack } from "../interface/track.interface";

@Injectable()
export class DTrack implements ITrack {


    constructor(
        @InjectRepository(Track) private trackRepository: Repository<Track>,
        private dataSource: DataSource,
        private minioClientService: MinioClientService,
    ) { }


    /**
      * 歌单-新增-我收藏的歌曲
      * @param songForm 
      * @returns 
      */
    async createFavorite(userId: number, { id }: FavoriteForm): Promise<void> {
        //插入favor_user_song表的数据
        await this.trackRepository
            .createQueryBuilder('track')
            .relation(Track, 'favoriteUsers')
            .of(id)
            .add(userId)//多对多关系 新增与收藏者的关系
    }


    /**
    * 歌单-删除-我收藏的歌曲
    * @param songForm 
    * @returns 
    */
    async deleteFavorite(userId: number, { id }: FavoriteForm): Promise<void> {
        await this.trackRepository
            .createQueryBuilder('track')
            .relation(Track, 'favoriteUsers')
            .of(id)
            .remove(userId)//多对多关系 删除与收藏者的关系
    }

    /**
    * 歌单-删除-我收藏的歌曲
    * @param songForm 
    * @returns 
    */
    async myfavorite(userId: number, { pageNum, pageSize, trackName }: TrackPageQuery): Promise<[Array<Track>, number]> {
        const build = await this.trackRepository
            .createQueryBuilder("track")
            .leftJoinAndSelect("track.songList", "song")
            .leftJoinAndSelect("track.tagList", "genre")
            .leftJoinAndSelect("track.pic", "file_info_pic")
            .leftJoinAndSelect("track.favoriteUsers", "favor_user")
            .select([
                'track.id',
                'track.title',
                'track.createTime',
                'track.isActive',
                'track.desc',
                'track.createTime',
                'song.id',
                'song.title',
                'genre.id',
                'genre.categoryName',
                'file_info_pic.id',
                'file_info_pic.percentage',
                'file_info_pic.url',
                'file_info_pic.name',
                'file_info_pic.mimeType',
                'file_info_pic.uid',
                'file_info_pic.lastModified',
            ])
            .orderBy("track.createTime", 'DESC')
            .offset((pageNum - 1) * pageSize)
            .limit(pageSize);

        if (userId) {
            build.where('favor_user.id = :userId', { userId })
        }

        return await build.getManyAndCount();
    }


    /**
     * 歌单-推荐列表
     * @param username 
     * @param pageNum 
     * @param pageSize 
     * @returns 
     */
    async getRecommendList(username: string, pageNum: number = 1, pageSize: number = 10): Promise<[Track[], number]> {
        const build = await this.trackRepository
            .createQueryBuilder("track")
            .leftJoinAndSelect("track.songList", "song")
            .leftJoinAndSelect("track.tagList", "genre")
            .leftJoinAndSelect("track.pic", "file_info_pic")
            .select([
                'track.id',
                'track.title',
                'track.createTime',
                'track.isActive',
                'track.desc',
                'track.createTime',
                'song.id',
                'song.title',
                'genre.id',
                'genre.categoryName',

                'file_info_pic.id',
                'file_info_pic.percentage',
                'file_info_pic.url',
                'file_info_pic.name',
                'file_info_pic.mimeType',
                'file_info_pic.uid',
                'file_info_pic.lastModified',
            ])
            .orderBy("track.createTime", 'DESC')
            .offset((pageNum - 1) * pageSize)
            .limit(pageSize)

        if (username) {
            build.leftJoinAndSelect("track.favoriteUsers", "favor_user", "favor_user.username = :useranme")
                .setParameter('useranme', username)
                .addSelect([
                    'favor_user.id',
                    'favor_user.username',
                ])
        }

        return await build.getManyAndCount();
    }

    async page(username: string, pageNum: number, pageSize: number, trackName: string, tagId: number): Promise<[Track[], number]> {
        const build = await this.trackRepository
            .createQueryBuilder("track")
            .leftJoinAndSelect("track.songList", "song")
            .leftJoinAndSelect("track.tagList", "genre")
            .leftJoinAndSelect("track.pic", "file_info_pic")
            // .leftJoinAndSelect("track.favoriteUsers", "favor_user", "favor_user.username = :useranme")
            // .setParameter('useranme', username)
            .select([
                'track.id',
                'track.title',
                'track.createTime',
                'track.isActive',
                'track.desc',
                'track.createTime',
                'song.id',
                'song.title',
                'genre.id',
                'genre.categoryName',
                // 'favor_user.id',
                // 'favor_user.username',
                'file_info_pic.id',
                'file_info_pic.percentage',
                'file_info_pic.url',
                'file_info_pic.name',
                'file_info_pic.mimeType',
                'file_info_pic.uid',
                'file_info_pic.lastModified',
            ])
            .orderBy("track.createTime", 'DESC')
            .offset((pageNum - 1) * pageSize)
            .limit(pageSize)

        if (username) {
            build.leftJoinAndSelect("track.favoriteUsers", "favor_user", "favor_user.username = :useranme")
                .setParameter('useranme', username)
                .addSelect([
                    'favor_user.id',
                    'favor_user.username',
                ])
        }
        if (trackName) {
            build.where('track.title like :keywords', { keywords: `%${trackName}%` });
        }
        if (tagId) {
            build.where("genre.id = :tagId", { tagId })
        }
        return await build.getManyAndCount();
    }
    
    async getOne(id: number, username: string): Promise<Track> {
        const build = await this.trackRepository
            .createQueryBuilder("track")
            .leftJoinAndSelect("track.songList", "song")
            .leftJoinAndSelect("track.tagList", "genre")
            .leftJoinAndSelect("track.pic", "file_info_pic")
            .leftJoinAndSelect("song.rateFileInfos", "rate_file_info")
            .leftJoinAndSelect("song.artistList", "song_artist")
            .leftJoinAndSelect("song.album", "album")
            // .leftJoinAndSelect("track.favoriteUsers", "favor_user", "favor_user.username = :useranme")
            // .setParameter('useranme', username)
            .select([
                'track.id',
                'track.title',
                'track.createTime',
                'track.isActive',
                'track.desc',
                'track.createTime',
                'song.id',
                'song.title',
                'song.isVip',
                'song.payModel',
                'song.sort',
                'genre.id',
                'genre.categoryName',
                'album.id',
                'album.title',
                'rate_file_info.size',
                'rate_file_info.rate',
                'rate_file_info.format',
                'rate_file_info.duration',
                'song_artist.id',
                'song_artist.name',
                'file_info_pic.id',
                'file_info_pic.percentage',
                'file_info_pic.url',
                'file_info_pic.name',
                'file_info_pic.mimeType',
                'file_info_pic.uid',
                'file_info_pic.lastModified'
            ]).where("track.id = :id", { id })
        if (username) {
            build.leftJoinAndSelect("track.favoriteUsers", "favor_user", "favor_user.username = :useranme")
                .setParameter('useranme', username)
                .addSelect([
                    'favor_user.id',
                    'favor_user.username',
                ])
        }

        const data = await build.getOne();

        return data
    }

}